package com.example.demo;

import com.example.api.JobApi;
import com.example.api.JobExecutor;
import com.example.api.dto.ExecuteUserDTO;
import com.example.api.dto.TiggerDTO;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.smartboot.http.common.enums.HttpStatus;
import org.smartboot.http.server.HttpRequest;
import org.smartboot.http.server.HttpResponse;
import org.smartboot.http.server.HttpServerHandler;

import java.io.IOException;
import java.util.Map;

/**
 * @author fanhang
 */
public class SmartHttpHandler extends HttpServerHandler {
    private static final String APPLICATION_JSON = "application/json";
    private final byte[] bytes404;
    private final JsonMapper jsonMapper;
    private final JobExecutor jobExecutor;

    public SmartHttpHandler(JsonMapper jsonMapper, JobExecutor jobExecutor) throws JsonProcessingException {
        this.jsonMapper = jsonMapper;
        this.jobExecutor = jobExecutor;
        this.bytes404 = jsonMapper.writeValueAsBytes(Map.of("message", "not-found"));
    }

    @Override
    public void handle(HttpRequest request, HttpResponse response) {
        response.setContentType(APPLICATION_JSON);
        try {
            Object result = this.dispatch(request.getRequestURI(), request.getInputStream().readAllBytes());
            this.write(response, HttpStatus.OK, result);
        } catch (UnsupportedOperationException e) {
            this.write(response, HttpStatus.NOT_FOUND, bytes404);
        } catch (Exception e) {
            this.write(response, HttpStatus.INTERNAL_SERVER_ERROR, Map.of("message", e.getMessage()));
        }
    }

    private Object dispatch(String uri, byte[] data) {
        if (uri.endsWith("/")) {
            uri = uri.substring(0, uri.length() - 1);
        }
        if (uri.startsWith(JobApi.EXECUTE_USER)) {
            return this.jobExecutor.executeUser(decode(data, ExecuteUserDTO.class));
        }
        if (uri.startsWith(JobApi.TIGGER)) {
            return this.jobExecutor.tigger(decode(data, TiggerDTO.class));
        }
        throw new UnsupportedOperationException("不支持");
    }

    private <T> T decode(byte[] data, Class<T> clazz) {
        try {
            return jsonMapper.readValue(data, clazz);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void write(HttpResponse response, HttpStatus status, Object data) {
        try {
            response.setHttpStatus(status.value(), status.getReasonPhrase());
            response.write(jsonMapper.writeValueAsBytes(data));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void write(HttpResponse response, HttpStatus status, byte[] data) {
        try {
            response.setHttpStatus(status.value(), status.getReasonPhrase());
            response.write(data);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
